/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.controller.admin;

import cn.easyplatform.lang.Strings;
import cn.easyplatform.messages.request.SimpleRequestMessage;
import cn.easyplatform.messages.vos.admin.CacheVo;
import cn.easyplatform.messages.vos.admin.CachesVo;
import cn.easyplatform.spi.service.AdminService;
import cn.easyplatform.type.IResponseMessage;
import cn.easyplatform.web.dialog.MessageBox;
import cn.easyplatform.web.service.ServiceLocator;
import org.zkoss.util.resource.Labels;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.OpenEvent;
import org.zkoss.zk.ui.select.SelectorComposer;
import org.zkoss.zk.ui.select.annotation.Listen;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zul.*;

import java.util.*;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class TableController extends SelectorComposer<Component> implements EventListener<Event> {

    @Wire("grid#seqList")
    private Grid seqList;

    @Wire("grid#lockList")
    private Grid lockList;

    @Wire("bandbox#findSeq")
    private Bandbox findSeq;

    @Wire("bandbox#findLock")
    private Bandbox findLock;

    private List<Object[]> seqData;

    private List<Object[]> lockData;

    private Map<String, Group> group = new HashMap<String, Group>();

    @Override
    public void doAfterCompose(Component comp) throws Exception {
        super.doAfterCompose(comp);
        if (!fetchData("init"))
            comp.detach();
    }

    private boolean fetchData(String type) {
        AdminService as = ServiceLocator.lookup(AdminService.class);
        IResponseMessage<?> resp = as.table(new SimpleRequestMessage(type));
        if (resp.isSuccess()) {
            if ("init".equals(type)) {
                List<Object[]>[] data = (List<Object[]>[]) resp.getBody();
                drawSeqList(seqData = data[0]);
                drawLockList(lockData = data[1]);
            } else if ("Seq".equals(type)) {
                drawSeqList((List<Object[]>) resp.getBody());
            } else {
                drawLockList((List<Object[]>) resp.getBody());
            }
        } else
            MessageBox.showMessage(resp);
        return resp.isSuccess();
    }

    private void drawSeqList(List<Object[]> data) {
        seqList.getRows().getChildren().clear();
        for (Object[] cv : data) {
            Row row = new Row();
            row.appendChild(new Label((String) cv[0]));
            row.appendChild(new Label(cv[1].toString()));
            row.appendChild(new Label(cv[2].toString()));
            Button refresh = new Button();
            refresh.setIconSclass("z-icon-edit");
            refresh.setTooltiptext(Labels.getLabel("admin.table.seq.edit"));
            refresh.addEventListener(Events.ON_CLICK, this);
            row.setValue(cv);
            row.appendChild(refresh);
            row.setValue(cv);
            seqList.getRows().appendChild(row);
        }
    }

    private void drawLockList(List<Object[]> data) {
        lockList.getRows().getChildren().clear();
        group.clear();
        for (Object[] cv : data) {
            Group g = group.get(cv[0]);
            if (g == null) {
                g = new Group((String) cv[0]);
                g.setParent(lockList.getRows());
                group.put(g.getLabel(), g);
            }
            Row row = new Row();
            row.appendChild(new Label((String) cv[1]));
            row.appendChild(new Label((String) cv[2]));
            row.appendChild(new Label((String) cv[5]));
            row.appendChild(new Label((String) cv[3]));
            row.appendChild(new Label(cv[4].toString()));
            Button delete = new Button();
            delete.setIconSclass("z-icon-times");
            delete.setSclass("ml-2");
            delete.setTooltiptext(Labels.getLabel("button.remove"));
            delete.setParent(row);
            delete.addEventListener(Events.ON_CLICK, this);
            row.setValue(cv);
            lockList.getRows().getChildren().add(lockList.getRows().getChildren().indexOf(g) + 1, row);
        }
    }

    @Listen("onOpen=bandbox#findSeq;onOpen=bandbox#findLock")
    public void onSearch(OpenEvent oe) {
        String key = (String) oe.getValue();
        String type = oe.getTarget().getId().substring(4);
        if (!Strings.isBlank(key)) {
            if (type.equals("Seq")) {
                if (seqData == null || seqData.isEmpty())
                    return;
                List<Object[]> searchs = new ArrayList<>();
                for (Object[] vo : seqData) {
                    if (((String) vo[0]).contains(key))
                        searchs.add(vo);
                }
                drawSeqList(searchs);
            } else {
                if (lockData == null || lockData.isEmpty())
                    return;
                List<Object[]> searchs = new ArrayList<>();
                for (Object[] vo : lockData) {
                    if (((String) vo[0]).contains(key))
                        searchs.add(vo);
                }
                drawLockList(searchs);
            }
        } else {
            fetchData(type);
        }
    }

    @Override
    //@Listen("onClick=grid#applist > rows > row > hlayout > a")
    public void onEvent(Event event) throws Exception {
        if (event.getTarget().getParent() instanceof Vlayout) {
            Longbox input = (Longbox) event.getTarget().getAttribute("input");
            reset((Row) event.getTarget().getAttribute("c"), input.getValue());
            event.getTarget().getRoot().detach();
        } else {
            Row row = (Row) event.getTarget().getParent();
            if (row.getGrid() == seqList) {
                Object[] data = row.getValue();
                Vlayout vlayout = new Vlayout();
                vlayout.setSpacing("10px");
                Longbox input = new Longbox();
                input.setValue(((Number) data[1]).longValue());
                input.setHflex("1");
                input.setHeight("30px");
                input.setPlaceholder(Labels.getLabel("admin.table.seq.placeholder"));
                input.setConstraint("no negative,no zero,no empty");
                vlayout.appendChild(input);
                Button btn = new Button(Labels.getLabel("button.ok"));
                btn.setHflex("1");
                btn.setHeight("30px");
                btn.addEventListener(Events.ON_CLICK, this);
                btn.setAttribute("c", row);
                btn.setAttribute("input", input);
                vlayout.appendChild(btn);
                Window dialog = new Window(Labels.getLabel("admin.table.seq.edit") + ":" + data[0], "normal", true);
                dialog.setPage(row.getPage());
                dialog.setWidth("300px");
                //dialog.setHeight("120px");
                dialog.appendChild(vlayout);
                dialog.doModal();
            } else {
                remove(row);
            }
        }
    }

    private void reset(Row row, long value) {
        Object[] data = row.getValue();
        data[1] = value;
        AdminService as = ServiceLocator.lookup(AdminService.class);
        IResponseMessage<?> resp = as.table(new SimpleRequestMessage(row.getValue()));
        if (resp.isSuccess()) {
            ((Label) row.getFirstChild().getNextSibling()).setValue(value + "");
        } else
            MessageBox.showMessage(resp);
    }

    private void remove(final Row row) {
        Messagebox.show(Labels.getLabel("admin.service.op.confirm", new String[]{Labels.getLabel("button.remove")}), Labels.getLabel("admin.service.op.title"), Messagebox.NO | Messagebox.OK,
                Messagebox.QUESTION, new EventListener<Event>() {
                    @Override
                    public void onEvent(Event event) throws Exception {
                        if (event.getName().equals(Events.ON_OK)) {
                            AdminService as = ServiceLocator.lookup(AdminService.class);
                            IResponseMessage<?> resp = as.table(new SimpleRequestMessage(row.getValue()));
                            if (resp.isSuccess()) {
                                if (row.getGroup().getItemCount() == 1)
                                    row.getGroup().detach();
                                row.detach();
                            } else
                                MessageBox.showMessage(resp);
                        }
                    }
                });
    }
}
